package com.wang.wx.listener;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.wang.wx.entity.EmailUser;
import com.wang.wx.entity.sout.PhoneToEmailModel;
import com.wang.wx.service.EmailUserService;
import lombok.extern.slf4j.Slf4j;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class PhoneToEmailExcelDataListener extends AnalysisEventListener<PhoneToEmailModel> {

    private final ExecutorService executorService;
    /** 模板 */
    private final List<PhoneToEmailModel> phoneToEmailModels = new CopyOnWriteArrayList<>();
    private final EmailUserService emailUserService;
    private final ExcelWriter excelWriter;
    private final WriteSheet writeSheet;
    private final Lock lock = new ReentrantLock();
    private final int BATCH_SIZE = 1000;

    public PhoneToEmailExcelDataListener(EmailUserService emailUserService, String outputFilePath) {
        this.emailUserService = emailUserService;

        // 创建 ExcelWriter 实例和 WriteSheet 实例
        //获取outputFilePath的目录，但是outputFilePath是一个文件路径，只创建目录不需要文件名
        Path parent = Paths.get(outputFilePath).getParent();
        try {
            Files.createDirectories(parent);
            this.excelWriter = EasyExcel.write(outputFilePath, PhoneToEmailModel.class).build();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("创建 ExcelWriter 实例和 WriteSheet 实例失败");
        }
        this.writeSheet = EasyExcel.writerSheet("Sheet1").build();

        // 创建固定大小的线程池
        this.executorService = Executors.newFixedThreadPool(10);
    }

    /**
     * 每读一行就会执行这个方法
     *
     * @param phoneToEmailModel
     * @param context
     */
    @Override
    public void invoke(PhoneToEmailModel phoneToEmailModel, AnalysisContext context) {
        phoneToEmailModels.add(phoneToEmailModel);
        if (phoneToEmailModels.size() >= BATCH_SIZE) {
            processCurrentBatch();
        }
    }
    

    /**
     * 所有数据读取完成后执行
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 处理剩余的批次
        if (!phoneToEmailModels.isEmpty() && phoneToEmailModels.size() < BATCH_SIZE) {
            processCurrentBatch();
        }
        executorService.shutdown();
        try {
            executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        // 处理完成后关闭 ExcelWriter
        excelWriter.finish();
    }

    private void processCurrentBatch() {
        List<PhoneToEmailModel> batchToProcess = new ArrayList<>(phoneToEmailModels);
        phoneToEmailModels.clear();
        executorService.submit(() -> processBatch(batchToProcess));
    }

    private void processBatch(List<PhoneToEmailModel> phoneToEmailModels) {
        for (PhoneToEmailModel model : phoneToEmailModels) {
            processCompanyData(model);
        }
        // 写入数据时加锁
        lock.lock();
        try {
            excelWriter.write(phoneToEmailModels, writeSheet);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 根据手机获取微信号
     * @param model
     */
    private void processCompanyData(PhoneToEmailModel model) {
        List<EmailUser> emailUsers = emailUserService.getByPhone(model.getPhone());
        if (ObjectUtil.isNotEmpty(emailUsers) && emailUsers.size() > 0) {
            EmailUser emailUser = emailUsers.get(0);
            model.setEmail(emailUser.getEmail());
        }
    }
}